const axios = require('axios');
const config = require('../config');
const log = require('./log');

class OptimusApi {
  constructor() {
    this.token = null;
  }

  async callApi(params) {
    log.info('_callApi() started. option=\n', JSON.stringify(params));
    if (this.isTokenExpired()) {
      await this.getAccessToken();
    }

    const {
      uri, method, data, ...rest
    } = params;
    const options = {
      url: `${config.api.url}${uri}`,
      method,
      data,
      headers: {
        Authorization: this.token.access_token,
      },
      timeout: 30000,
      ...rest,
    };
    try {
      const { data: result } = await axios(options);
      log.info('_callApi() completed. ');
      return result;
    } catch (e) {
      log.error('_callApi() error', e);
      throw e;
    }
  }

  async getAccessToken() {
    const options = {
      url: config.auth.tokenUrl,
      method: 'POST',
      auth: {
        username: config.auth.clientId,
        password: config.auth.clientSecret,
      },
      params: {
        grant_type: 'client_credentials',
        client_id: config.auth.clientId,
      },
    };
    try {
      const { data: result } = await axios(options);
      result.issued_at = Date.now();
      log.info('_getAccessToken() completed. ');
      this.token = result;
    } catch (e) {
      log.error('_getAccessToken() error', e);
      throw e;
    }
  }

  isTokenExpired() {
    if (!this.token) {
      return true;
    }
    const { issued_at, expires_in } = this.token;
    return Date.now() - issued_at > (expires_in - 5) * 1000;
  }
}

module.exports = new OptimusApi();
